package org.garbagecan.hibernatestudy.m2m;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Test {
	private static Logger logger = LoggerFactory.getLogger(Test.class);
	
	private static SessionFactory sessionFactory;
	
	public static void main(String[] args) throws Exception {
		init();
		test1();
		test2();
		test3();
		test4();
	}

	private static void test1() throws Exception {
		Session session = getSession();
		Transaction t = session.beginTransaction();
		User user1 = new User();
		user1.setName("user_1");
		session.persist(user1);

		User user2 = new User();
		user2.setName("user_2");
		session.persist(user2);

		Group group = new Group();
		group.setName("group_1");
		Set<User> users = new HashSet<User>();
		users.add(user1);
		users.add(user2);
		group.setUsers(users);
		session.persist(group);

		t.commit();
		session.close();
	}

	private static void test2() throws Exception {
		Session session = getSession();
		List users = getSession().createCriteria(User.class).list();
		session.close();
		logger.info(users.toString());

		session = getSession();
		List groups = getSession().createCriteria(Group.class).list();
		session.close();
		logger.info(groups.toString());
	}

	private static void test3() throws Exception {
		Session session = getSession();
		Transaction t = session.beginTransaction();

		Set<User> userSet = new HashSet<User>();
		for (int i = 0; i < 10; i++) {
			User user = new User();
			user.setName("user_" + i);
			userSet.add(user);
			session.persist(user);
		}

		for (int i = 0; i < 10; i++) {
			Group group = new Group();
			group.setName("group_" + i);
			group.setUsers(userSet);
			session.persist(group);
		}

		t.commit();
		session.close();

		session = getSession();
		List users = getSession().createCriteria(User.class).list();
		session.close();
		for (Object obj : users) {
			User user = (User)obj;
			logger.info(user.getName() + " - group size: " + user.getGroups().size());
		}

		session = getSession();
		List groups = getSession().createCriteria(Group.class).list();
		session.close();
		for (Object obj : groups) {
			Group group = (Group)obj;
			logger.info(group.getName() + " - user size: " + group.getUsers().size());
		}
	}
	
	private static void test4() throws Exception {
		Session session = getSession();
		Transaction t = session.beginTransaction();

		Set<User> userSet = new HashSet<User>();
		for (int i = 0; i < 100; i++) {
			User user = new User();
			user.setName("user_" + i);
			userSet.add(user);
			session.persist(user);
		}

		Set<Group> groupSet = new HashSet<Group>();
		for (int i = 0; i < 100; i++) {
			Group group = new Group();
			group.setName("group_" + i);
			group.setUsers(userSet);
			groupSet.add(group);
			session.persist(group);
		}

		for (int i = 0; i < 100; i++) {
			Role role = new Role();
			role.setName("role_" + i);
			role.setUsers(userSet);
			role.setGroups(groupSet);
			session.persist(role);
		}
		t.commit();
		session.close();

		session = getSession();
		List users = getSession().createCriteria(User.class).list();
		session.close();
		for (Object obj : users) {
			User user = (User)obj;
			logger.info(user.getName() + " - group size: " + user.getGroups().size());
			logger.info(user.getName() + " - role size: " + user.getRoles().size());
		}

		session = getSession();
		List groups = getSession().createCriteria(Group.class).list();
		session.close();
		for (Object obj : groups) {
			Group group = (Group)obj;
			logger.info(group.getName() + " - user size: " + group.getUsers().size());
			logger.info(group.getName() + " - role size: " + group.getRoles().size());
		}

		session = getSession();
		List roles = getSession().createCriteria(Role.class).list();
		session.close();
		for (Object obj : roles) {
			Role role = (Role)obj;
			logger.info(role.getName() + " - user size" + role.getUsers().size());
			logger.info(role.getName() + " - group size" + role.getGroups().size());
		}
	}

	private static Session getSession() throws Exception {
		return sessionFactory.openSession();
	}
	
	private static void init() throws Exception {
		if (sessionFactory == null) {
			File file = new File(Test.class.getResource("/org/garbagecan/hibernatestudy/m2m/hibernate.cfg.xml").getFile());
			Configuration configuration = new Configuration().configure(file);
			sessionFactory = configuration.buildSessionFactory();
			new SchemaUpdate(configuration).execute(true, true);
		}
	}
}
